package edu.gatech.cs2340.teamrocket.control.guicontrol;

import java.util.ArrayList;
import java.util.List;
import java.text.DecimalFormat;
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

import edu.gatech.cs2340.teamrocket.control.exception.InvalidTransactionException;
import edu.gatech.cs2340.teamrocket.model.Model;
import edu.gatech.cs2340.teamrocket.model.item.Item;
import edu.gatech.cs2340.teamrocket.model.storage.*;
import edu.gatech.cs2340.teamrocket.view.*;
import edu.gatech.cs2340.teamrocket.view.shop.*;
/**
 *
 * @author Wai Chip Ngai
 *
 * This is the controller for the whole shopping experience in the game to work
 * It also creates the 5 panels that make up the GUI
 */
public class ShopControl implements ActionListener {

	private final static int BUTTON_HEIGHT = 58;
	private final static int BUTTON_WIDTH = 248;
	private final static int LABEL_HEIGHT = 22;
	private final static int LABEL_WIDTH = 767;
	private final static int ITEM_WIDTH = 81;
	private final static int ITEM_HEIGHT = 41;
    private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.00");
    
    private final JButton clear = new JButton(new ImageIcon("img/shop_graphics/clear.png"));
	private final ImageIcon clearClicked = new ImageIcon("img/shop_graphics/clear_clicked.png");
    private final JButton exit = new JButton(new ImageIcon("img/shop_graphics/exit.png"));
	private final ImageIcon exitClicked = new ImageIcon("img/shop_graphics/exit_clicked.png");
    private final JButton complete = new JButton(new ImageIcon("img/shop_graphics/complete.png"));
    private final ImageIcon completeClicked = new ImageIcon("img/shop_graphics/complete_clicked.png");

    // model
    private Model model;
    private ShopInventory shopInventory;

    // gui components
    //private JPanel mainShop, titlePanel, ShopPanel, buttonPanel;
    private JPanel mainGUI;
    private JLabel pMoneyLabel,weightLabel,sMoneyLabel, welcome;
    private List<JRadioButton> buyList, sellList;
    private List<JSpinner> spinnerList;
    private List<JLabel> PILabel, SILabel;
    private List<JButton>all;

    // control
    private GameFrame gf;
    private MainGamePanelControl gameControl;

    /**
     * initializes instance variables by taking in a player inventory
     * creates the panels and add items to them
     * @param pi player inventory
     */
    public ShopControl(GameFrame gf, MainGamePanelControl gameControl, ShopInventory SI){
        this.gameControl = gameControl;
        this.gf=gf;
        model = Model.getInstance();
        shopInventory = SI;
        //create panels
        mainGUI = new ShopGUI();

        pMoneyLabel = new JLabel("Player Money: $"+DECIMAL_FORMAT.format(model.getBackpackMoney()),JLabel.CENTER);
        
        weightLabel = new JLabel("Available Weight: "+DECIMAL_FORMAT.format(model.getBackpackAvailableWeight()),JLabel.CENTER);
        sMoneyLabel = new JLabel("Shop Money: $"+DECIMAL_FORMAT.format(shopInventory.getMoney()),JLabel.CENTER);
        welcome = new JLabel("Hello, " + model.getTrainerName()+
                "! Welcome to this awesome shop!!",JLabel.CENTER);
        int currentXPosition = 129;
        int currentYPosition = 14;
        welcome.setBounds(currentXPosition, currentYPosition,LABEL_WIDTH,LABEL_HEIGHT);
        currentYPosition += LABEL_HEIGHT;
        sMoneyLabel.setBounds(currentXPosition, currentYPosition,LABEL_WIDTH,LABEL_HEIGHT);
        currentYPosition += LABEL_HEIGHT;
        pMoneyLabel.setBounds(currentXPosition, currentYPosition,LABEL_WIDTH,LABEL_HEIGHT);
        currentYPosition += LABEL_HEIGHT;
        weightLabel.setBounds(currentXPosition, currentYPosition,LABEL_WIDTH,LABEL_HEIGHT);
        clear.setBounds(80, 672, BUTTON_WIDTH, BUTTON_HEIGHT);
        clear.setRolloverIcon(clearClicked);
        exit.setBounds(388, 672, BUTTON_WIDTH, BUTTON_HEIGHT);
        exit.setRolloverIcon(exitClicked);
        complete.setBounds(696, 672, BUTTON_WIDTH, BUTTON_HEIGHT);
        complete.setRolloverIcon(completeClicked);
        clear.addActionListener(this);
        exit.addActionListener(this);
        complete.addActionListener(this);
        clear.setOpaque(true);
        clear.setBorderPainted(false);
        exit.setOpaque(true);
        exit.setBorderPainted(false);
        complete.setOpaque(true);
        complete.setBorderPainted(false);
        //add labels to the panel
        mainGUI.add(sMoneyLabel);
        mainGUI.add(pMoneyLabel);
        mainGUI.add(weightLabel);
        mainGUI.add(clear);
        mainGUI.add(exit);
        mainGUI.add(complete);
        mainGUI.add(welcome);
        //adding items to the main shopping panel
        addShoppingPanelLabel();
        gf.add(mainGUI, GameFrame.SHOP_GUI_JPANEL);
        commit();

    }
    /**
     * Return to the main gaming window when the user tries to exit the shop
     */
    public void exit(){
        gameControl.refreshInventoryPanel();
        gf.showPanel(GameFrame.MAIN_GAME_JAPNEL);
    }
    /**
     * reset the JSpinners and JComboBoxes
     */
    public void clear(){
        for (JRadioButton buyButton: buyList){
            buyButton.setSelected(true);
        }
        for (JSpinner amount: spinnerList){
            amount.setValue(0);
        }
    }
    /**
     * Update the labels to show the current money and available weight
     * also the amount items in both the player's inventory and the shop's inventory
     */
    private void updateLabels(){
        //update money and weight labels
        pMoneyLabel.setText("Player Money: $"+DECIMAL_FORMAT.format(model.getBackpackMoney()));
        weightLabel.setText("Available Weight: "+DECIMAL_FORMAT.format(model.getBackpackAvailableWeight()));
        sMoneyLabel.setText("Shop Money: $"+DECIMAL_FORMAT.format(shopInventory.getMoney()));
        // update the player's and shop's inventories
        int index = 0;
        for (Item item : Item.values()){
            PILabel.get(index).setText("" + model.getBackpackQuantity(item));
            SILabel.get(index).setText("" + shopInventory.getQuantity(item));
            index++;
        }
    }

    /**
     * Add labels to the main shopping panel
     */
    private void addShoppingPanelLabel(){
        //initialize the lists that carry info about the spinners, comboboxes, and labels
        buyList = new ArrayList<JRadioButton>();
        sellList = new ArrayList<JRadioButton>();
        spinnerList = new ArrayList<JSpinner>();
        PILabel = new ArrayList<JLabel>();
        SILabel = new ArrayList<JLabel>();
        all = new ArrayList<JButton>();
        int currentXPos = 88;
        int currentYPos = 175;
        int hGap = 14;
        int vGap = 35;
        //loop through inventories to add prices and items onto the main shopping panel
        int index = 0;
        for (Item item : Item.values()) {
            //get prices and weight
            double buyPrice = item.getPrice();
            double sellPrice = item.getPrice()* ShopInventory.BUYBACK_RATIO;
            double itemWeight = item.getWeight();
            JLabel nameLabel = new JLabel(item.toString(),JLabel.CENTER);
            nameLabel.setBounds(currentXPos, currentYPos, ITEM_WIDTH, ITEM_HEIGHT);
            currentXPos += hGap+ITEM_WIDTH;
            //create labels
            JLabel buyPriceLabel = new JLabel("$"+DECIMAL_FORMAT.format(buyPrice),JLabel.CENTER);
            buyPriceLabel.setBounds(currentXPos, currentYPos, ITEM_WIDTH, ITEM_HEIGHT);
            currentXPos += hGap+ITEM_WIDTH;
            JLabel sellPriceLabel = new JLabel("$"+DECIMAL_FORMAT.format(sellPrice),JLabel.CENTER);
            sellPriceLabel.setBounds(currentXPos, currentYPos, ITEM_WIDTH, ITEM_HEIGHT);
            currentXPos += hGap+ITEM_WIDTH;
            
            JLabel itemWeightLabel = new JLabel(DECIMAL_FORMAT.format(itemWeight),JLabel.CENTER);
            itemWeightLabel.setBounds(currentXPos, currentYPos, ITEM_WIDTH, ITEM_HEIGHT);
            currentXPos += hGap+ITEM_WIDTH;
            
            JLabel shopAmountLabel = new JLabel("" + shopInventory.getQuantity(item),JLabel.CENTER);
            shopAmountLabel.setBounds(currentXPos, currentYPos, ITEM_WIDTH, ITEM_HEIGHT);
            currentXPos += hGap+ITEM_WIDTH;
            
            JLabel playerAmountLabel = new JLabel("" + model.getBackpackQuantity(item),JLabel.CENTER);
            playerAmountLabel.setBounds(currentXPos, currentYPos, ITEM_WIDTH, ITEM_HEIGHT);
            currentXPos += hGap+ITEM_WIDTH;
            //add labels to list
            PILabel.add(playerAmountLabel);
            SILabel.add(shopAmountLabel);
            //create buy and selling radio buttons
            ButtonGroup mode = new ButtonGroup();
            JPanel modePanel = new JPanel();
            modePanel.setBounds(currentXPos+hGap/3, currentYPos-vGap/3, ITEM_WIDTH, 60);
            modePanel.setBackground(new Color(0,0,0,0));
            currentXPos += hGap+ITEM_WIDTH;
            JRadioButton buy = new JRadioButton("Buy");
            buy.setBackground(Color.WHITE);
            buy.setSelected(true);
            JRadioButton sell = new JRadioButton("Sell");
            sell.setBackground(Color.WHITE);
            mode.add(buy);
            mode.add(sell);
            modePanel.add(buy);
            modePanel.add(sell);
            //modePanel.setBorder(BorderFactory.createLineBorder(Color.black));
            //JComboBox comboBox = new JComboBox(shopMode.values());
            //comboBox.setMaximumRowCount(2);
            //add radio buttons to list
            buyList.add(buy);
            sellList.add(sell);

            //create spinners
            JSpinner aSpinner = new JSpinner();
            int maxAmount = shopInventory.getQuantity(item);
            aSpinner.setModel(new SpinnerNumberModel(0,0,maxAmount,1));
            aSpinner.setBounds(currentXPos+hGap/2, currentYPos, ITEM_WIDTH, ITEM_HEIGHT);
            currentXPos += hGap+ITEM_WIDTH;
            //add spinners to list
            spinnerList.add(aSpinner);

            //add buy all buttons
            JButton aButton = new JButton("All");
            aButton.addActionListener(new BuyAllListener());
            aButton.setBounds(currentXPos+hGap/2, currentYPos, ITEM_WIDTH, ITEM_HEIGHT);
            currentXPos += hGap+ITEM_WIDTH;
            all.add(aButton);
            //add labels and items to the main shopping panel
            mainGUI.add(nameLabel);
            mainGUI.add(buyPriceLabel);
            mainGUI.add(sellPriceLabel);
            mainGUI.add(itemWeightLabel);
            mainGUI.add(shopAmountLabel);
            mainGUI.add(playerAmountLabel);
            mainGUI.add(modePanel);
            mainGUI.add(aSpinner);
            mainGUI.add(aButton);
            mainGUI.add(new JLabel(""));
            index++;
            currentYPos += vGap + ITEM_HEIGHT;
            currentXPos = 88;
        }

    }


    /**
     * Helper for the commit function.
     * determine which item to buy or to sell
     * @param index the index represeting the individual item
     * @return how much each item are buying or selling
     */
    private int getItemQuantityChange(int index){
        int quantity = (Integer)spinnerList.get(index).getValue();
        if(buyList.get(index).isSelected() == true) // buy
            return quantity;
        else // sell
            return -quantity;
    }

    /**
     * When the player presses complete transaction,
     * it handles all the math and logic.
     */
    public void commit(){
        // pretend to complete the transaction and validate both inventories
        BasicStorage si = shopInventory.clone();
        BasicStorage pi = model.cloneBackpack();

        for(int index = 0; index < Item.values().length; index++){
            Item i = Item.values()[index];
            int quantity = getItemQuantityChange(index);
            if(quantity < 0){
                // player sell
                quantity = -quantity;
                pi.sellItem(i, quantity);
                si.buyItem(i, quantity);
            }
            else{
                // player buy
                pi.buyItem(i, quantity);
                si.sellItem(i, quantity);
            }
        }
        try{
            pi.validate();
            si.validate();

            shopInventory.become(si);
            model.setInventory(pi);

            updateLabels();
        }
        catch(InvalidTransactionException e){
            //what happens when a transaction is not valid
            JOptionPane.showMessageDialog(null, e.getMessage());
            return;
        }
    }


    private class BuyAllListener implements ActionListener{
        public void actionPerformed(ActionEvent e){
            int index = all.indexOf((JButton)e.getSource());
            if (buyList.get(index).isSelected())
                spinnerList.get(index).setValue(shopInventory.getQuantity(Item.values()[index]));
            else
                spinnerList.get(index).setValue(model.getBackpackQuantity(Item.values()[index]));
        }
    }


	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getSource().equals(exit)){
			exit();
		}else if(e.getSource().equals(clear)){
			clear();
		}else{
			commit();
		}
		
	}

}
